package com.demo.webapp.kcfinder.utils;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 值栈上下文
 * 持久化环境上下文及操作结果
 * 
 * @author ryuu.kk
 *
 */
public class ValueContext extends Object implements Map<String, Object> {
	
	public static final String CONTEXT_CONTEXT_KEY = "context";
    public static final String ROOT_CONTEXT_KEY = "root";
    public static final String THIS_CONTEXT_KEY = "this";
    
    private static Map<String, Object> RESERVED_KEYS = new HashMap<String, Object>(5);
    
    private Map<String, Object> _values = new HashMap<String, Object>(23);
    
    private Object _root;
    private Object _currentObject;
    
    static {
        RESERVED_KEYS.put(CONTEXT_CONTEXT_KEY, null);
        RESERVED_KEYS.put(ROOT_CONTEXT_KEY, null);
        RESERVED_KEYS.put(THIS_CONTEXT_KEY, null);
    }
    
    public ValueContext() {
    	
    }
    
    public ValueContext(Map<String, Object> values) {
        super();
        this._values = values;
    }
    
    public void setCurrentObject(Object value) {
        _currentObject = value;
    }
    
    public Object getCurrentObject() {
        return _currentObject;
    }
    
    public void setValues(Map<String, Object> value) {
        for(Iterator<String> it = value.keySet().iterator(); it.hasNext();) {
            String k = it.next();
            _values.put(k, value.get(k));
        }
    }

    public Map<String, Object> getValues() {
        return _values;
    }
    
    public void setRoot(Object value) {
        _root = value;
    }

    public Object getRoot() {
        return _root;
    }
    
	@Override
	public Object get(Object key) {
		Object result = null;
		if (RESERVED_KEYS.containsKey(key)) {
			if (key.equals(ValueContext.THIS_CONTEXT_KEY)) {
				result = getCurrentObject();
			} else {
				if (key.equals(ValueContext.ROOT_CONTEXT_KEY)) {
					result = getRoot();
				} else {
					if (key.equals(ValueContext.CONTEXT_CONTEXT_KEY)) {
						result = this;
					}
				}
			}
		} else {
			result = _values.get(key);
		}
		return result;
	}

	@Override
	public Object put(String key, Object value) {
		Object result = null;
		if (RESERVED_KEYS.containsKey(key)) {
			if (key.equals(ValueContext.THIS_CONTEXT_KEY)) {
				result = getCurrentObject();
				setCurrentObject(value);
			} else {
				if (key.equals(ValueContext.ROOT_CONTEXT_KEY)) {
					result = getRoot();
					setRoot(value);
				} else {
					if (key.equals(ValueContext.CONTEXT_CONTEXT_KEY)) {
						//result = this;
						throw new IllegalArgumentException("can't change " + ValueContext.CONTEXT_CONTEXT_KEY
                                + " in context");
					}
				}
			}
		} else {
			result = _values.get(key);
		}
		return result;
	}

	@Override
	public Object remove(Object key) {
		Object result = null;
		if (RESERVED_KEYS.containsKey(key)) {
			if (key.equals(ValueContext.THIS_CONTEXT_KEY)) {
				result = getCurrentObject();
				setCurrentObject(null);
			} else {
				if (key.equals(ValueContext.ROOT_CONTEXT_KEY)) {
					result = getRoot();
					setRoot(null);
				} else {
					if (key.equals(ValueContext.CONTEXT_CONTEXT_KEY)) {
						throw new IllegalArgumentException("can't remove "
								+ ValueContext.CONTEXT_CONTEXT_KEY
								+ " from context");
					}
				}
			}
		} else {
			result = _values.remove(key);
		}
		return result;
	}
	
	@Override
	public int size() {
		return this._values.size();
	}

	@Override
	public boolean isEmpty() {
		return this._values.isEmpty();
	}

	@Override
	public boolean containsKey(Object key) {
		return _values.containsKey(key);
	}

	@Override
	public boolean containsValue(Object value) {
		return _values.containsValue(value);
	}

	@Override
	public void putAll(Map<? extends String, ? extends Object> m) {
		_values.putAll(m);
	}

	@Override
	public void clear() {
		setRoot(null);
        setCurrentObject(null);
		_values.clear();
	}

	@Override
	public Set<String> keySet() {
		return _values.keySet();
	}

	@Override
	public Collection<Object> values() {
		return _values.values();
	}

	@Override
	public Set<java.util.Map.Entry<String, Object>> entrySet() {
		return _values.entrySet();
	}
}